package com.chen.util;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;
import java.util.Scanner;

/**
 * 这是自己在学习Java时，收集做过的工具进行汇总
 * 希望能够形成一个比较完成的工具类供自己使用
 */
public class StudyUtils {
    private static final Random random = new Random();

    // 将构造方法隐藏
    private StudyUtils() {
    }

    /**
     * 封装传送给客户端的消息
     * 最终返回的字符串格式：
     * 陈江河 2025-06-06 08:34:34 周六 下午
     * 消息内容
     *
     * @param msg      消息
     * @param userName 用户名
     * @return 传送给客户端的消息
     */
    public static String getMsgStr(String msg, String userName) {
        // 使用StringBuilder拼接字符串
        StringBuilder sb = new StringBuilder();
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 设置时间格式
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a");
        String nowStr = dtf.format(now);
        return sb.append(userName).append(" ").append(nowStr).append("\r\n")
                .append(" ").append(msg).append("\r\n").toString();
    }


    /**
     * 判断一个二维数组是否为空
     * 以下这些情况都认为是空
     * int[][] arr1 = new int[2][2];
     * int[][] arr2 = new int[2][];
     * int[][] arr3 = new int[2][0];
     * int[][] arr4 = new int[0][2];
     * int[][] arr5 = {};
     * int[][] arr8 = {null,{}};
     * int[][] arr9 = {{},null};
     *
     * @param arr 需要判断的二维数组
     * @return 返回是否为空
     */
    public static boolean isTwoArrayEmpty(int[][] arr) {
        boolean isEmpty = arr == null || arr.length == 0;
        if (!isEmpty) {
            for (int[] arr1 : arr) {
                if (arr1 != null && arr1.length > 0) {
                    for (int i : arr1) {
                        isEmpty = i == 0;
                    }
                    if (!isEmpty) break;
                } else {
                    isEmpty = true;
                }
            }
        }

        return isEmpty;
    }

    /**
     * 将一个数字分解成一位一位的
     * 例如：target = 234
     * 分解成：
     * 第一位: 2
     * 第一位: 3
     * 第一位: 4
     *
     * @param target 需要分解的数字
     */
    public static void parseInteger(int target) {
        // 判断数据是多少位
        int count = String.valueOf(target).length();
        int temp = target;
        for (int i = 1; i <= count; i++) {
            int tep = temp % 10;
            System.out.println("第" + i + "位:" + tep);
            temp = temp / 10;
        }
    }

    /**
     * 计算圆形的面积
     *
     * @param r 半径
     * @return 圆形的面积
     */
    public static double calculateArea(double r) {
        return Math.PI * r * r;
    }

    /**
     * 计算长方形面积
     *
     * @param length 长
     * @param width  宽
     * @return 方形面积
     */
    public static double calculateArea(double length, double width) {
        return length * width;
    }

    /**
     * 计算梯形面积
     *
     * @param a 上底
     * @param b 下底
     * @param c 高
     * @return 形面积
     */
    public static double calculateArea(double a, double b, double c) {
        return (a + b) * c / 2;
    }

    /**
     * 找素数,start-end之内的素数
     *
     * @param start 开始数字
     * @param end   结束数字
     */
    public static void getPrimeNumber(int start, int end) {
        // 素数：只能被1和本身整除的对象
        begin:
        for (int i = start; i <= end; i++) {
            for (int j = 2; j <= Math.sqrt(i); j++) {
                if (i % j == 0) {
                    continue begin;
                }
            }
            System.out.println(i);
        }
    }

    /**
     * 生成多位随机验证码，验证码包含英数字
     *
     * @param n 指定需要生成的位数
     * @return 符合指定要求的字符串验证码
     */
    public static String test(int n) {
        // 因为英数字在ASCII码中时连续编号
        // 使用StringBuilder
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            // 获取随机数 生成随机数有点难控制
            int num = random.nextInt(10);// 难点
            char upper = (char) (random.nextInt(26) + 65);// 难点
            char lower = (char) (random.nextInt(26) + 97);// 难点

            // 这次随机选择 num,upper,lower
            int switchNum = random.nextInt(3);// 难点
            switch (switchNum) {
                case 0:
                    sb.append(num);
                    break;
                case 1:
                    sb.append(upper);
                    break;
                case 2:
                    sb.append(lower);
                    break;
            }
        }
        return sb.toString();
    }

    /**
     * 将整数数组元素反转
     *
     * @param arr 目标数组
     */
    public static void reverseArray(int[] arr) {
        for (int i = 0; i < arr.length / 2; i++) {
            swap(arr, i, arr.length - 1 - i);
        }
    }

    /**
     * int[][] arr = new int[n][m]
     * 打乱上述类型的二维数组顺序
     *
     * @param arr 目标数组
     */
    public static void shuffleArray(int[][] arr) {
        for (int i = 0; i < arr.length; i++) {
            int first = random.nextInt(arr.length);
            for (int j = 0; j < arr[i].length; j++) {
                int second = random.nextInt(arr[i].length);
                swap(arr[i], j, second);
            }
        }
    }

    /**
     * 实现 Fisher-Yates 算法
     * 也就是将一维数组顺序打乱
     */
    public static <T> void shuffleArray(T[] array) {
        for (int i = array.length - 1; i > 0; i--) {
            // 获取一个 [0, i] 之间的随机整数
            int index = random.nextInt(i + 1);
            // 交换 array[i] 和 array[index]
            T temp = array[index];
            array[index] = array[i];
            array[i] = temp;
        }
    }

    /**
     * 获取一副扑克牌
     */
    public static String[] getCards() {
        // 首先需要获取到做牌需要到的元素
        // 做牌
        String[] cards = new String[54];
        String[] arr = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
        String[] colors = {"♡", "♢", "♤", "♧"};
        int index = 0;
        for (String num : arr) {
            for (String color : colors) {
                cards[index++] = num + color;
            }
        }
        cards[index++] = "小王";
        cards[index] = "小王";
        return cards;
    }

    /**
     * 选择排序
     *
     * @param arr 需要排序的数组
     */
    public static void selectSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] > arr[j]) {
                    // 选择排序，是将将第一个元素固定一个一个比较，一次类推
                    swap(arr, i, j);
                }
            }
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int num = arr[i];
        arr[i] = arr[j];
        arr[j] = num;
    }

    /**
     * 冒泡排序
     *
     * @param arr 需要排序的数组
     */
    public static void popSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 冒泡排序，是两两相邻数组比较
                    swap(arr, j, j + 1);
                }
            }
        }
    }

    /**
     * 判断两个数组是否相等
     * 标准：长度, 内容, 顺序完全相同
     *
     * @param arr1 数组a
     * @param arr2 数组b
     * @return true, 两个数组相等；false,不相等
     */
    public static boolean isArrayEquals(int[] arr1, int[] arr2) {
        if (arr1 == null && arr2 == null) return false;
        boolean flag = (arr1 != null && arr2 != null) && arr1.length == arr2.length;
        if (flag) {
            for (int i = 0; i < arr1.length; i++) {
                if (arr1[i] != arr2[i]) {
                    flag = false;
                    break;
                }
            }
        }
        return flag;
    }

    /**
     * 查找元素在数组中的索引位置
     * 如果找到则返回索引，否则返回-1
     *
     * @param arr     目标数组
     * @param element 目标元素
     * @return true, return index;false,return -1
     */
    public static int getIndexByElement(int[] arr, int element) {
        if (arr == null || arr.length == 0) return -1;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == element) {
                return i;
            }
        }
        return -1;
    }
}

